# coding: iso-8859-1
"""A Reinteract module to present regular expression matches.

Licence: GPL v2 or above.

Tero Jäntti 2007, 2008, 2009
Ideas and fixes by Eduardo de Oliveira Padoan
"""
from reinteract.custom_result import CustomResult
from re import \
    IGNORECASE, LOCALE, MULTILINE,\
    DOTALL, UNICODE, VERBOSE,\
    I, L, M, S, U, X
import gtk, pango, re

def search(pattern, string, flags=0):
    return ReMatchResult(string, pattern, flags, ReMatchResult.SEARCH)

def match(pattern, string, flags=0):
    return ReMatchResult(string, pattern, flags, ReMatchResult.MATCH)

def sub(pattern, repl, string, count=0):
    flags = (0 if isinstance(pattern, basestring) else pattern.flags)
    return ReSubResult(string, pattern, flags, repl, count)


class ReResult(CustomResult):
    """Represents the results of different regexp operations."""

    def __init__(self, string, pattern, flags):
        self.string = string
        if isinstance(string, str):
            self.string = string.decode("UTF-8")
        if isinstance(pattern, basestring):
            pattern = re.compile(pattern, flags)
        self.exp = pattern

    def create_text(self, string):
        text = gtk.TextBuffer()
        text.set_text(string)
        self.highlight_tags = [
            text.create_tag(background="#00FF00"),
            text.create_tag(background="#30BB30")
            ]
        return text

    def highlight(self, text, start, end, parity):
        text.apply_tag(
            self.highlight_tags[parity],
            text.get_iter_at_offset(start),
            text.get_iter_at_offset(end))

    def create_view(self, text):
        view = gtk.TextView(text)
        view.set_editable(False)
        return view


class ReMatchResult(ReResult):
    """Represents match objects of a regexp operation.

    Highlights the matched parts of the string with different font
    colors and properties. The groups of a match are highlighted as
    well. Can be used with both match and search functions."""

    MATCH = 0
    SEARCH = 1

    def __init__(self, string, pattern, flags, method):
        ReResult.__init__(self, string, pattern, flags)
        self.method = method

    def highlight_match(self, text, match, parity):
        if not match: return
        self.highlight(text, match.start(), match.end(), parity)
        for i in range(1, len(match.groups()) + 1):
            gstart, gend = match.span(i)
            if gstart > -1:
                text.apply_tag(
                    self.group_tags[i%2],
                    text.get_iter_at_offset(gstart),
                    text.get_iter_at_offset(gend))

    def create_widget(self):
        text = self.create_text(self.string)
        self.group_tags = [
            text.create_tag(underline=pango.UNDERLINE_SINGLE),
            text.create_tag(underline=pango.UNDERLINE_DOUBLE)
            ]

        if self.method == self.SEARCH:
            parity = 0
            for m in self.exp.finditer(self.string):
                self.highlight_match(text, m, parity)
                parity = (parity + 1) % 2
        else: # MATCH
            self.highlight_match(text, self.exp.match(self.string), 0)

        return self.create_view(text)


class ReSubResult(ReResult):
    """Represents the string returned by sub().

    The replacements are highlighted."""

    def __init__(self, string, pattern, flags, repl, count):
        ReResult.__init__(self, string, pattern, flags)
        self.repl = repl
        self.count = count

    def create_widget(self):
        text = self.create_text(
            self.exp.sub(self.repl, self.string) )

        partial = self.string
        parity = 0
        pos = 0
        n = self.count
        if not self.count:
            n = len(self.exp.findall(self.string))

        for i in range(n):
            start_block = partial[:pos]
            end_block = partial[pos:]
            start, end = self.exp.search(end_block).span()

            s = end_block[start:end]
            ss = self.exp.sub(self.repl, s, 1)
            
            partial = start_block + self.exp.sub(self.repl, end_block, 1)
            pos += start
            self.highlight(text, pos, pos+len(ss), parity)
            pos += len(ss)
            parity = (parity + 1) % 2

        return self.create_view(text)
